{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# How to use the `metrics` utility to monitor network traffic"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Author: Kris Stern"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Intro**: The `metrics` utility is located at the `syft/generic` directory. In it is defined the `NetworkMonitor` class, with `get_packets` and `read_packet` as two separate static methods. The `get_packets` function is the go-to tool for sniffing on the network with pyshark, which is a Python wrapper for TShark/Wireshark, itself a free and open-source packet analyzer. Further info regarding pyshark can be found at https://github.com/KimiNewt/pyshark, whereas more info regarding Wireshark can be found at the official Wiki at https://wiki.wireshark.org/FrontPage. So `get_packets` yields the `capture` and `length` objects, where `capture` is a LiveCapture generated by pyshark, and where `length` is the number of packets in `capture`. Furthermore, the `read_packet` is a convenience function designed to read a single packet given the LiveCapture output from `get_packets` and an index which is between `0` and `length - 1` (complying with Python indexing convention which starts from `0`)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. How to use `get_packets` to sniff on a network"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from syft.generic.metrics import NetworkMonitor"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Say we are sniffing on a WiFi network with interface `'en0'`, timeout of 60 seconds, and display filter `'tcp.port == 8777'` (i.e. suppose Alice's port is 8777):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "capture, length = NetworkMonitor.get_packets(interface='en0', timeout=60, display_filter = 'tcp.port == 8777')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To investigate each individual packet in the LiveCapture object called `capture`, we can do the following:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "packet0 = capture[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then we can do many things with this `packet0` object, including the following:\n",
    "1. captured length\n",
    "2. eth\n",
    "3. frame_info\n",
    "4. get_multiple_layers\n",
    "5. get_raw_packet\n",
    "6. highest_layer\n",
    "7. interface_captured\n",
    "8. ip\n",
    "9. layers\n",
    "10. length\n",
    "11. number\n",
    "12. pretty_print\n",
    "13. show\n",
    "14. sniff_time\n",
    "15. sniff_timestamp\n",
    "16. tcp\n",
    "17. transport_layer\n",
    "\n",
    "For example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "packet0.tcp.pretty_print()  # This is essentially a `<bound method Layer.pretty_print of <TCP Layer>>`. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "packet0.show()  # This is simply the `<bound method Packet.pretty_print of <TCP Packet>>`. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "packet0.layers  # To show the layers in the packet. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To check on how many packets have been captured in the event during timeout:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(length)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. How to use `read_packet` to read packets obtained with `get_packets` individually"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As a convenience function, the `read_packet` method has been introduced to be used in tandem with the `get_packets` method to show individual packet info. \n",
    "\n",
    "Say if there are 999 packets in `capture`, then we can do the following right after the above steps to generate a `pretty_print` output of all four layers - ETH, IP, and TCP, TLS - of the packet:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "NetworkMonitor.read_packet(index=13, capture_input=capture)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
